home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
graphics
/
3dvect37.zip
/
3D3.ASM
< prev
next >
Wrap
Assembly Source File
|
1994-06-22
|
38KB
|
1,249 lines
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
;
; Filename : 3d3.asm
; Included from: Main Assembley Module
; Description : 3d vector routines - fast sorting method with tolerenced full sorting (3d1+3d2)
;
; Written by: John McCarthy
; 1316 Redwood Lane
; Pickering, Ontario.
; Canada, Earth, Milky Way (for those out-of-towners)
; L1X 1C5
;
; Internet/Usenet: BRIAN.MCCARTHY@CANREM.COM
; Fidonet: Brian McCarthy 1:229/15
; RIME/Relaynet: ->CRS
;
; Home phone, (905) 831-1944, don't call at 2 am eh!
;
; Send me your protected mode source code!
; Send me your Objects!
; But most of all, Send me a postcard!!!!
;
; - objects can pass through one another and still be sorted correctly
; - maxsurfs and maxpoints must be large - set to TOTAL points/surfs on screen
;
; To use:
;
; call draw_landscape ; draw background landscape
; call clear_fill ; clear video memory (last screen)
; call look_at_it ; make camera look at selected object
; call setsincose ; set rotation multipliers for eye
; call show_stars ; plot background stars (if you want)
; call makeobjs ; plot all objects in sides table
; call instant_mouse ; plot mouse on screen
; call flip_page ; flip video pages
; call resetupd ; reset update for borders
; call updvectors ; move objects around, rotate them
;
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
.386p
jumps
code32 segment para public use32
assume cs:code32, ds:code32
; define externals
include pmode.ext ; protected mode externals
include xmouse.ext ; xmode mouse externals
include xmode.ext ; xmode externals by matt pritchard
include irq.ext
include font.ext
include macros.inc
include equ.inc
include vars3.inc ; labels and such
align 16
include arctan.inc ; inverse tan
include sin.inc ; sin/cosin table
include math.inc ; rotate, cos,sin,arctan...
include xscale.inc
include poly.inc ; common ploygon stuff
include more.inc ; more common 3d/graphics stuff
public makeobjs
public make1obj
public flush_surfaces
public init_tables
strip_bytes equ 8
align 16
abort_all:
add esp,strip_bytes ; abort from loadpoints and make1obj
ret ; returning now from makeobjs call
align 16
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Loadpoints: Begin loading of points from object definition data into array
; In:
; ESI -> object #
; Out:
; ESI -> offset of connection data
; Given ESI as object number. rotate, translate and convert to 3d the points
; of that object. returns edi as pointer to sides.
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
loadpoints:
mov bl,userotate[esi] ; rotation type
mov si,whatshape[esi*2] ; get shape
mov esi,objbase[esi*4]
view_is_not_ok:
mov eax,[esi]
add esi,8
cmp eax,zad ; check if too far to see detail anyway
jb s view_is_not_ok
mov eax,[esi-4]
add esi,eax
llkk:
movzx eax,w [esi]
mov numpoints,eax
or eax,eax
jz no_points_anyway
mov edi,pointindex ; set xp,yp,zp pointer
shl eax,2
add eax,pointindex ; pointindex = word indexer to last point
cmp eax,maxpoints*4-4 ; test for overflow in points tables
jae abort_all
mov ax,[esi+2]
mov numsides,eax
add eax,showing
cmp eax,maxsurfaces-1 ; check for overflow in "sides" tables
jae abort_all
add esi,4+25*2 ; skip point and side totals, skip future data
mov lindex,edi ; set last index to points (this one)
add edi,4 ; compensate for center of gravity point
middle_load_points:
test bl,no_rotation ; check userotate command
jnz np13 ; use different loop if no rotation
np12:
movsx ebx,w [esi] ; x
movsx ecx,w [esi+2] ; y
movsx ebp,w [esi+4] ; z
push edi esi
call rotate ; rotate based on object matrix
add ebp,zad
cmp ebp,ztruncate
jge s ntrunct
neg ebp
cmp ebp,ztruncate
jge s ntrunct
mov ebp,ztruncate
ntrunct:
add ebx,xad
add ecx,yad
call make3d
pop esi edi
mov xp[edi],ebx
mov yp[edi],ecx
mov zp[edi],ebp
add edi,4 ; inc xp indexer
add esi,6 ; inc input pointer
dec numpoints
jne s np12
mov pointindex,edi ; save for next call of loadpoints
ret ; esi exits with pointer to sides
no_points_anyway:
mov ax,[esi+2]
mov numsides,eax
add eax,showing
cmp eax,maxsurfaces-1 ; check for overflow in "sides" tables
jae abort_all
add esi,4+25*2 ; skip point and side totals, skip future data
mov edi,pointindex ; set xp,yp,zp pointer
add pointindex,4
mov lindex,edi ; set last index to points (this one)
ret
np13:
movsx ebx,w [esi] ; x
movsx ecx,w [esi+2] ; y
movsx ebp,w [esi+4] ; z
push edi esi
call erotate ; rotation matrix already set up! (camera)
add ebp,zad
cmp ebp,ztruncate
jge s ntrunct2
neg ebp
cmp ebp,ztruncate
jge s ntrunct2
mov ebp,ztruncate
ntrunct2:
add ebx,xad
add ecx,yad
call make3d
pop esi edi
mov xp[edi],ebx
mov yp[edi],ecx
mov zp[edi],ebp
add edi,4 ; inc xp indexer
add esi,6
dec numpoints
jne s np13
mov pointindex,edi ; save for next call of loadpoints
ret
align 16
special_commands dd offset dobitmap
dd offset dobitmap
dd offset pushmatrix
dd offset popmatrix
dd offset pushlocation
dd offset poplocation
dd offset newobject
dd offset no_new_matrix
dd offset gosub_function ; 8
dd offset return_function ; 9
dd offset goto_function ; 10
number_ofb dw 5*2
dw 5*2
dw 1*2
dw 1*2
dw 1*2
dw 1*2
dw 1*2
dw 1*2
dw ? ; gosub_function
dw ? ; return_function
dw ? ; goto_function
align 16
gosub_function:
push esi
movsx eax,w [esi]
add esi,eax
jmp return_iteration
align 16
return_function:
pop esi
add esi,2
jmp return_iteration
align 16
goto_function:
movsx eax,w [esi]
add esi,eax
jmp return_iteration
align 16
pushmatrix:
push vmatrix+0
push vmatrix+4
push vmatrix+8
push vmatrix+12
push vmatrix+16
push vmatrix+20
push vmatrix+24
push vmatrix+28
push vmatrix+32
jmp return_iteration
align 16
popmatrix:
pop vmatrix+32
pop vmatrix+28
pop vmatrix+24
pop vmatrix+20
pop vmatrix+16
pop vmatrix+12
pop vmatrix+8
pop vmatrix+4
pop vmatrix+0
jmp return_iteration
align 16
pushlocation:
push xad
push yad
push zad
jmp return_iteration
align 16
poplocation:
pop zad
pop yad
pop xad
jmp return_iteration
align 16
ld_special:
mov cx,ax
and ecx,special-1 ; max 127 commands
jmp [special_commands+ecx*4]
align 16
; handle loading of bitmap from object list
;
; eg dw himap,8,5,50,60 ;command is 32,point 8, bitmap 5, x&y scaling of 50,60
dobitmap:
align 16
lodsw ; get from si, first is point
shl eax,2
add eax,lindex ; add to include offset in list
stosw ; put in sides table
mov edx,ebp ; save indexer
movzx ebp,ax ; get point indexers
mov eax,zp[ebp]
mov zeds[ebx*2],eax ; set zed for sort.
mov ebp,edx
movsw ; get bitmap type
movsd ; get x then y scaling
mov edx,command ; get command (for iteration bits)
mov textures[ebx],dx
cmp zad,64000 ; bitmaps farther than 65536 screw up
jge no_norml ; you can't see them anyway. prevent overflow
jmp ln3
align 16
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Loadsides: Load connection data from object data definition
; In:
; ESI -> offset of connection data
; Out: null
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
loadsides:
mov lamflag,no
mov edi,offsides ; get ready for lodsw and stosw
mov ebp,edi ; ebp = offset to first point in side
mov ebx,showing ; bx = word indexer for surfaces
shl ebx,1
ld_lp:
mov ax,[esi] ; get command word
add esi,2
mov command,eax
test eax,special ; if bitmap, do special load,
jnz ld_special ; or test previous color
mov eax,[esi] ; get texture data/type
mov texture12,eax
mov eax,[esi+4] ; get colour, high byte is other side
add esi,8
mov colors12,eax
mov ecx,lindex ; quick add for loop
push ebp
push ebx
movzx eax,w [esi] ; get from esi, first is unconditinal
add esi,2
shl eax,2
add eax,ecx ; add to include offset in list
mov [edi],ax ; put in edi
add edi,2
mov edx,eax
ld_loop:
lodsw ; get from esi
shl eax,2
add eax,ecx
mov [edi],ax ; put in edi
cmp eax,edx ; check all after first point
je s ld_exitloop
lodsw
shl eax,2
add eax,ecx
mov [edi+2],ax
cmp eax,edx
je s ld_exitloop
lodsw
shl eax,2
add eax,ecx
mov [edi+4],ax
cmp eax,edx
je s ld_exitloop
lodsw
shl eax,2
add eax,ecx
mov [edi+6],ax
add edi,8
cmp eax,edx
jne s ld_loop
ld_exitloop:
push esi
mov edi,ebp ; adjust bp into appropriate indexer
movzx ebp,w [edi+2]
mov ecx,[zp+ebp]
mov ebp,edx ; get point indexers
add ecx,[zp+ebp] ; take average of two z points for sort
mov zeds[ebx*2],ecx
mov edx,command
test edx,onscr ; find if test is for on screen pixels
jnz test_if_on_screen
test dl,both ; check if always visible
jnz its_line
return_screen:
mov edx,[xp+ebp] ; first point
mov ebx,[yp+ebp]
mov bp,[edi+2]
mov esi,[xp+ebp] ; second point
mov ecx,[yp+ebp]
mov bp,[edi+4]
mov edi,[xp+ebp] ; third point
mov ebp,[yp+ebp]
call checkfront ; check if side is visable using p1,2,3
pop esi ebx ebp ; return object data pointer
mov edx,command
or ecx,ecx
jle s test_shading ; cx>-1 if side visible, skip if not
test edx,double ; test to use other colour
jz s skipit ; miss this side...
shr texture12,16
shr colors12,16
xor w texture12,inverse ; do inverse shading
test_shading:
test texture12,shade+last
jnz handle_shading ; shading bit set, do it...
ln2:
test edx,check ; find out if side is only a test side
jnz s no_show
mov eax,texture12 ; another side added...
mov textures[ebx],ax
movzx eax,w colors12
add eax,palxrefx ; get offset of palette cross reference table for this object
mov ax,[eax]
mov surfcolors[ebx],ax
ln3:
inc showing ; another side added...
add ebx,2
add ebp,maxpolys*2 ; bump ebp to next block
no_show:
test edx,iterate
jnz handle_surface_iteration
skipit:
test edx,normal ; do we skip surface normal data
jz s no_norml
add esi,6
no_norml:
test edx,iterate
jnz failed_iteration ; skip iteration data if surface failure
return_iteration:
mov edi,ebp ; set di for next stosw
dec numsides ; count for next side
jne ld_lp
mov offsides,edi ; save for next call
ret
align 16
its_line:
pop esi ebx ebp
test w texture12,shade+last
jz ln2
; handle gourad/lambert shading
align 16
handle_shading:
test w texture12,last ; test to use previous colour or bitmap call
jnz ld_do_previous
test w texture12,wavey
jnz ln2
push ebx esi ebp edx
cmp lamflag,no ; is lambert matrix set up?
je s setitup ; jump to less likely route
returnq:
mov bx,word ptr [esi] ; get surface normal
mov cx,word ptr [esi+2]
mov bp,word ptr [esi+4]
add esi,6
call lrotate ; rotate surface normal by lambert matrix
pop edx
test w texture12,inverse ; have the sides flipped? test dx,256
jnz s invert_colour ; jump to least likely route
lp_contin:
add edi,256
shr edi,1 ; result -256 to +256, turn into 0-256
mov al,b shading_tables[edi] ; now into 0-15
xor ah,ah
pop ebp esi ebx
add w colors12,ax ; user can have offset color in object!
jmp ln2
align 16
invert_colour: ; inversion occures with other side option,
neg edi ; always visible option, and shading option
jmp lp_contin ; all combined!
align 16
setitup:
push esi
mov esi,currobj ; this is object # from make1obj
call lambert ; set up lambert maxtrix
mov lamflag,yes
pop esi
jmp s returnq
align 16
ld_do_previous:
mov ax,w colors12
mov cx,surfcolors[ebx-2]
and cx,shading_bits ; drop old colour block, keep shading indexer (from math.inc)
add ecx,eax ; add new colour block
mov w colors12,cx
jmp ln2
; handle iteration option
align 16
handle_surface_iteration:
test edx,normal
jz s no_norml2
add esi,6 ; skip if shading normal present
no_norml2:
test edx,matrix ; test to derive new matrix
jz no_new_matrix
newobject:
mov edi,currobj ; new matrix, get offset object number
add di,[esi+16]
test onoff[edi],sub_object_on ; test if sub-object has been turned on...
jz failed_iteration
mov eax,[esi+24]
mov minzc,eax
mov eax,[esi+28]
mov btolr,eax
push ebx esi ebp edx ; save stuff before iteration handle
mov bx,w xs[edi*4] ; get rotation location
mov cx,w ys[edi*4]
mov bp,w zs[edi*4]
add bx,[esi+10]
add cx,[esi+12]
add bp,[esi+14]
movsx ebx,bx
movsx ecx,cx
movsx ebp,bp
push edi
call rotate ; z<>0, find rotation location
add xad,ebx
add yad,ecx
add zad,ebp
pop esi ; return object number+offset
test userotate[esi],no_rotation ; test to use new matrix or add to old
jnz do_compound_thingy
call temp_matrix ; add to old
call matrix_multiply
mov eax,minzc
cmp zad,eax ; check if new object will be behind camera
jg done_alterq
jmp failed_iterationq
do_compound_thingy:
call compound ; compound new matrix
mov eax,minzc
cmp zad,eax ; check if new object will be behind camera
jg done_alterq
jmp failed_iterationq
no_new_matrix:
test b [esi+8],centroid ; is there a centroid offset?
jz done_alter
mov eax,[esi+28]
mov btolr,eax
push ebx esi ebp edx ; save stuff before centroid handle
movsx ebx,w [esi+10] ; no new matrix command, find point
movsx ecx,w [esi+12] ; offset (addition)
movsx ebp,w [esi+14]
call rotate ; if found, add rotated point to xad,yad,zad
add xad,ebx
add yad,ecx
add zad,ebp
done_alterq:
sub zad,1
adc zad,1
mov ebx,xad ; test if new xad,yad,zad are within screen boundaries
mov ecx,yad
mov ebp,zad
cmul eax,ebx,ratiox ; use fast constant multiply fo 3d conversion
idiv ebp
movsx edx,xmins
sub edx,btolr
cmp eax,edx ; tolerance is max object size/ratio
jl failed_iterationq
movsx edx,xmaxs
add edx,btolr
cmp eax,edx
jge failed_iterationq
mov ebx,eax
cmul eax,ecx,ratioy
idiv ebp
movsx edx,ymins
sub edx,btolr
cmp eax,edx
jl failed_iterationq
movsx edx,ymaxs
add edx,btolr
cmp eax,edx
jge failed_iterationq
mov edi,pointindex
mov xp[edi],ebx
mov yp[edi],eax
mov zp[edi],ebp
add pointindex,4
pop edx ebp esi ebx
done_alter:
movzx eax,w [esi] ; get number of extra points in iteration
add esi,2
mov numpoints,eax ; set as counter
mov ecx,eax ; save number of extra points for later use
shl eax,2
add eax,pointindex ; pointindex = word indexer to last point
cmp eax,maxpoints*4 ; test for overflow in points tables
jae abort_all2
lodsw ; get number of sides in iteration
add numsides,eax
add eax,showing
cmp eax,maxsurfaces-1 ; check for overflow in "sides" tables
jae abort_all2
add esi,25*2
or ecx,ecx ; no new points to add? (just surfaces)
je return_iteration ; only sides added to iteration, done...
push ebx ebp edx ; save load and store locations
mov edi,currobj ; add more points to xp,yp,zp list
mov bl,userotate[edi] ; because iteration is visible
mov edi,pointindex ; movzx edi,pointindex
call middle_load_points
pop edx ebp ebx
jmp return_iteration
align 16
abort_all2:
add esp,strip_bytes ; abort from iteration and make1obj
ret ; returning now from makeobjs call
; perform test for option 1024 - generate iteration if points on screen.
; routine also tests if polygon crosses screen - eg no point is on the screen
; but the polygon covers the screen, like the front of a very big building.
align 16
test_if_on_screen:
xor bl,bl ; bl = quadrant flag
push edx edi ; save command
mov esi,ebp
tios:
mov ecx,xp[esi] ; cx, dx =(x,y) to test
mov edx,yp[esi]
mov ah,32 ; 32 16 8 determine where point is,
cmp cx,xmins ;1 x x x then or bl with location
jl s ytest ;2 x x x
mov ah,8 ;4 x x x
cmp cx,xmaxs ;
jge s ytest
mov ah,16
ytest:
mov al,1
cmp dx,ymins
jl s oritall
mov al,4
cmp dx,ymaxs
jge s oritall
cmp ah,16
je s on_screen ; a point is on the screen, generate side...
oritall:
or bl,ah ; point is not on the screen, but it may
or bl,al ; contribute to a polygon which covers the screen.
add edi,2 ; get next connection for another test
mov si,sides[edi]
cmp si,bp ; test if at last connection in iteration test
jne tios
xor al,al ; count number of bits in y (must be >2)
ror bl,1
adc al,0
ror bl,1
adc al,0
ror bl,1
adc al,0
cmp al,1
jbe s skipit2
xor al,al ; now count x (must be >2)
ror bl,1
adc al,0
ror bl,1
adc al,0
ror bl,1
adc al,0
cmp al,1
jbe s skipit2
on_screen:
pop edi edx
test edx,both ; side is on screen
jz return_screen ; test if alway visible
pop esi ebx ebp ; always, pop and test for shading
test edx,shade
jz ln2 ; no shading - do normal return
jmp handle_shading
skipit2:
pop edi edx esi ebx ebp
jmp skipit
; handle failure of option 512
align 16
failed_iterationq:
pop edx ebp esi ebx
failed_iteration:
movzx ecx,w [esi+4] ; number of bytes to skip in case of failure
mov ax,[esi+6] ; get number of points TOTAL in iteration
add esi,8
shl eax,2 ; in case iteration in iteration in iteration...
add w pointindex,ax
add esi,ecx
jmp return_iteration
align 16
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Make1obj: Handle plotting of object ESI
; In:
; ESI -> object #
; OUT:null
; Notes:
; Routine assumes object is already ON! note: esi not si!
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
make1obj:
mov lamflag,no
mov currobj,esi
mov ebx,xs[esi*4] ; displacement
sub ebx,eyex
mov ecx,ys[esi*4]
sub ecx,eyey
mov ebp,zs[esi*4]
sub ebp,eyez
test userotate[esi],s_himap+s_point ; check if bitmap or point
jnz mo_special
shr ebx,8 ; account for decimal places
test ebx,00800000h
jz s pm_1
or ebx, 0ff000000h
pm_1:
shr ecx,8
test ecx,00800000h
jz s pm_2
or ecx, 0ff000000h
pm_2:
shr ebp,8
test ebp,00800000h
jz s pm_3
or ebp, 0ff000000h
pm_3:
mov si,whatshape[esi*2] ; get shape
mov esi,objbase[esi*4] ; get header start
add esi,[esi+4] ; get first resolution
mov edi,[esi+14*2] ; get maximum distance seen
cmp ebx,edi ; check if within visible space
jnl s noa2 ; if object miles away, don't bother
cmp ebp,edi
jnl s noa2
cmp ecx,edi
jnl s noa2
neg edi
cmp ebp,edi
jl s noa2
cmp ebx,edi
jl s noa2
cmp ecx,edi
jg s mo_misout
noa2:
ret
mo_misout:
mov edi,dword ptr [esi+16*2]
mov eax,dword ptr [esi+18*2]
mov btolr,eax
call zsolve ; figure out camera displacement
cmp esi,edi ; check if behind camera, miminum dist.
jl s noa2
sub esi,1 ; make z non-zero
adc esi,1
call xsolve
mov xad,edi ; store 3d offsets
call make3dx ; now make object farther in 3d
movsx eax,xmins
sub eax,btolr
cmp edi,eax ; tolerance is max object size/ratio
jl s noa2
movsx eax,xmaxs
add eax,btolr
cmp edi,eax
jge s noa2
call ysolve ; solve y and set correct regs
mov yad,ecx
call make3dy ; now make object farther in 3d
movsx eax,ymins
sub eax,btolr
cmp ecx,eax
jl s noa2
movsx eax,ymaxs
add eax,btolr
cmp ecx,eax
jge noa2
mov zad,ebp
mov zedthis,ebp
mov esi,pointindex
mov xp[esi],ebx ; save center of gravity as point 0
mov yp[esi],ecx
mov zp[esi],ebp
mov esi,currobj ; pop original object number
xor ebx,ebx
mov bl,palxref[esi]
mov ebx,xreftable[ebx*4]
mov palxrefx,ebx
test userotate[esi],no_rotation ; test to call compound routine
jnz s mk_skipc ; skip if anything other than full rotations
call compound ; full rotation object, calc. matrix
mk_skipc:
call loadpoints ; load points and rotate, exit di=sides
jmp loadsides ; now load sides, starting at di
align 16
noa:
ret
align 16
; if userotate = 32 then draw bitmap at location x,y,z
mo_special:
mov edi,maxz*256
cmp ebx,edi ; check if within visible space
jnl s noa ; if object miles away, don't bother
cmp ebp,edi
jnl s noa
cmp ecx,edi
jnl s noa
neg edi
cmp ebp,edi
jl s noa
cmp ebx,edi
jl s noa
cmp ecx,edi
jl s noa
shr ebx,8 ; account for decimal places, /256
test ebx,00800000h
jz s pq_1
or ebx, 0ff000000h
pq_1:
shr ecx,8
test ecx,00800000h
jz s pq_2
or ecx, 0ff000000h
pq_2:
shr ebp,8
test ebp,00800000h
jz s pq_3
or ebp, 0ff000000h
pq_3:
call zsolve ; figure out camera displacement
cmp esi,minz ; check if behind camera, miminum dist.
jl noa2
call xsolve
mov xad,edi ; store 3d offsets
call make3dx ; now make object farther in 3d
cmp edi,xmit ; tolerance is max object size/ratio
jl noa
cmp edi,xmat
jge noa
call ysolve ; solve y and set correct regs
mov yad,ecx
call make3dy ; now make object farther in 3d
cmp ecx,ymit
jl noa
cmp ecx,ymat
jge noa
mov zad,ebp
mov zedthis,ebp ; store z for next sort
mov esi,currobj ; pop original object number
cmp pointindex,(maxpoints-1)*2 ; check if there is room in table
jge noa
cmp showing,maxsurfaces-1
jge noa
test userotate[esi],s_point ; is point or bitmap?
jnz mo_ispoint
cmp ebp,65535 ; far bitmaps screw up, abort
jge noa
mov edi,pointindex
mov [xp+edi],ebx ; set location of bitmap
mov [yp+edi],ecx
mov [zp+edi],ebp
mov edi,offsides
add offsides,maxpolys*2 ; update for next object/bitmap
mov ebx,showing
shl ebp,1 ; adjust so it's the same as loadsides
mov zeds[ebx*4],ebp ; set z sort indexer
inc showing ; one more surface...
xor ah,ah
mov al,userotate[esi]
mov textures[ebx*2],ax ; set command for bitmap
mov eax,pointindex
add pointindex,4
stosw
mov ax,whatshape[esi*2]
stosw
mov ax,vxs[esi*2] ; set x and y scales (stretching)
stosw
mov ax,vys[esi*2]
stosw
noa4:
ret
align 16
mo_ispoint:
cmp bx,xmins ; draw single point/bullet
jl s noa4
cmp bx,xmaxs
jge s noa4
cmp cx,ymins
jl s noa4
cmp cx,ymaxs ; ymaxs1 if larger pixel
jge s noa4
mov edi,pointindex
mov [xp+edi],ebx ; set location of point/bitmap
mov [yp+edi],ecx
mov [zp+edi],ebp
mov edi,offsides
add offsides,maxpolys*2 ; update for next object/bitmap
mov ebx,showing
shl ebx,1
shl ebp,1
mov zeds[ebx*2],ebp ; set z sort indexer
inc showing ; one more surface...
mov textures[ebx],64 ; set this command as point
mov surfcolors[ebx],bulletcolour ; only for variable colours
mov eax,pointindex
add pointindex,4
stosw
stosw
noa8:
ret
align 16
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Set_order: Initialize original order for plotting objects
; In=Out=null
; Notes: This is called by Flush_surfaces so no need for you to do it.
; This must be called every frame to re-initalize the order for polygon sorting
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
set_order:
mov ecx,showing
jcxz s non2_do
dec ecx
jz s non2_do
shl ecx,1
mov esi,ecx
shl esi,1
add esi,offset order
prc equ 8
cmp ecx,prc*2
jb s ordrloop
bigsloop:
i=0
rept prc
mov [esi+i],ecx
i=i-4
sub ecx,2
endm
jz s non2_do
sub esi,prc*4
cmp ecx,prc*2
jae s bigsloop
ordrloop:
mov [esi],ecx
sub esi,4
dec ecx
loop ordrloop
non2_do:
mov [order],0 ; fill last
ret
align 16
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Setmakeorder: Initialize original order for plotting objects
; In=Out=null
; Notes: This is called by init_tables so there is no need for you to do it.
; This must be called once at the beginging of the program to define
; in what order the objects must be plotted (back to front). The order is
; constantly being re-arranged as objects move in front an behind one another
; If you want to do windowing, save the makeorder table for each window.
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
set_makeorder:
i=0
rept maxobjects ; macro to produce unrolled loop
mov makeorder+i*2,i+1 ; set makeorder to 0,1,2,3,4
i=i+1
endm
ret
align 16
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Makeobjs: Make/plot all objects on current_page
; In=Out=null
; Notes: Called from your mainline animation routine, falls through to sort
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
makeobjs: ; make all objects, unrolled loop
mov offsides, offset sides ; clear table indexers for call
mov pointindex,0
mov zedthis,0 ; clear temp (last z location)
i=0
rept maxobjects
local itsoff, dont_flush
mov eax,32767 ; in case of abort
movzx esi,makeorder+i*2
test onoff[esi],mainobject_on ; check on/off
jz s itsoff
if i ne 0
movsx eax,finalzed+i*2 ; flush buffer if this object far away
sub eax,zedthis ; from last. dont flush if very close.
add eax,collision/2
cmp eax,collision
jae s dont_flush
call flush_surfaces ; flush previous object
dont_flush:
movzx esi,makeorder+i*2
endif
call make1obj ; put new object in buffer
mov eax,zedthis ; get z and save for re_sort, zedthis = temporary storage
itsoff:
mov finalzed+i*2,ax
i=i+1
endm
cmp showing,0 ; if objects have already been flushed, skip
je miss_flush
call flush_surfaces
miss_flush:
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Re_sort:Bubble sort for entire objects, fastest when already sorted (assumed)
; In=Out=null
; Notes: No need to ever call this routine as makeobjs falls through to here.
; This routine sorts the objects make order by the prevoius Z distance.
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
basedif equ offset makeorder - offset finalzed
re_sort:
mov ecx,maxobjects-1
mov edx,offset finalzed-2
xor ebx,ebx ; sort flag
xor esi,esi
nextccx:
add edx,2
mov esi,maxobjects*2-2+offset finalzed
nextddx:
sub esi,2
mov ax,[esi+2]
cmp ax,[esi]
jle s donotng
xchg ax,[esi] ; don't flip entire object, just indexers
xchg ax,[esi+2]
mov ax,basedif[esi+2]
xchg ax,basedif[esi]
xchg ax,basedif[esi+2]
inc ebx ; flag that one sorted
donotng:
cmp esi,edx
jnle s nextddx
or ebx,ebx ; re-sort until no more sorts
loopne s nextccx
quickex:
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Flush_surfaces: Sort and flush all surfaces from polygon buffer to screen
; In=Out=null
; Notes: called by makeobjs
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
flush_surfaces:
call set_order ; set ordering of sides
call sort_list ; sort sides according to z distance
call drawvect ; draw 'em on da screen
mov offsides, offset sides ; clear table indexers for call
mov pointindex,0
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Init_tables: Initialize ordering before beginning 3d animation
; In=Out=null
; Notes: Called by YOU. Different routines between 3d1,3d2 and 3d3
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
init_tables:
call set_makeorder
ret
code32 ends
end